package com.rickpan.repository;

import com.rickpan.entity.UploadSession;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 上传会话数据访问层
 */
@Repository
public interface UploadSessionRepository extends JpaRepository<UploadSession, String> {
    
    /**
     * 根据用户ID查找上传会话
     */
    List<UploadSession> findByUserIdOrderByCreatedAtDesc(Long userId);
    
    /**
     * 根据用户ID和状态查找上传会话
     */
    List<UploadSession> findByUserIdAndStatus(Long userId, UploadSession.UploadStatus status);
    
    /**
     * 根据文件SHA256查找上传会话
     */
    Optional<UploadSession> findByFileSha256(String fileSha256);
    
    /**
     * 根据用户ID和文件SHA256查找上传会话
     */
    Optional<UploadSession> findByUserIdAndFileSha256(Long userId, String fileSha256);
    
    /**
     * 查找过期的上传会话
     */
    @Query("SELECT us FROM UploadSession us WHERE us.expiresAt < :now")
    List<UploadSession> findExpiredSessions(@Param("now") LocalDateTime now);
    
    /**
     * 查找指定时间之前创建的会话
     */
    @Query("SELECT us FROM UploadSession us WHERE us.createdAt < :before")
    List<UploadSession> findSessionsCreatedBefore(@Param("before") LocalDateTime before);
    
    /**
     * 根据状态查找上传会话
     */
    List<UploadSession> findByStatus(UploadSession.UploadStatus status);
    
    /**
     * 统计用户的上传会话数量
     */
    @Query("SELECT COUNT(us) FROM UploadSession us WHERE us.userId = :userId AND us.status = :status")
    long countByUserIdAndStatus(@Param("userId") Long userId, @Param("status") UploadSession.UploadStatus status);
    
    /**
     * 删除过期的上传会话
     */
    @Modifying
    @Query("DELETE FROM UploadSession us WHERE us.expiresAt < :now")
    int deleteExpiredSessions(@Param("now") LocalDateTime now);
    
    /**
     * 删除指定状态的会话
     */
    @Modifying
    @Query("DELETE FROM UploadSession us WHERE us.status IN :statuses")
    int deleteByStatusIn(@Param("statuses") List<UploadSession.UploadStatus> statuses);
    
    /**
     * 更新会话状态
     */
    @Modifying
    @Query("UPDATE UploadSession us SET us.status = :status WHERE us.id = :id")
    int updateStatus(@Param("id") String id, @Param("status") UploadSession.UploadStatus status);
    
    /**
     * 更新已上传分片信息
     */
    @Modifying
    @Query("UPDATE UploadSession us SET us.uploadedChunks = :uploadedChunks WHERE us.id = :id")
    int updateUploadedChunks(@Param("id") String id, @Param("uploadedChunks") String uploadedChunks);
    
    /**
     * 批量更新过期会话状态
     */
    @Modifying
    @Query("UPDATE UploadSession us SET us.status = 'EXPIRED' WHERE us.expiresAt < :now AND us.status = 'UPLOADING'")
    int markExpiredSessions(@Param("now") LocalDateTime now);
    
    /**
     * 查找用户正在进行的上传会话
     */
    @Query("SELECT us FROM UploadSession us WHERE us.userId = :userId AND us.status = 'UPLOADING' AND us.expiresAt > :now")
    List<UploadSession> findActiveSessionsByUserId(@Param("userId") Long userId, @Param("now") LocalDateTime now);
    
    /**
     * 检查是否存在相同文件的上传会话
     */
    @Query("SELECT COUNT(us) > 0 FROM UploadSession us WHERE us.userId = :userId AND us.fileSha256 = :fileSha256 AND us.status IN ('UPLOADING', 'COMPLETED')")
    boolean existsByUserIdAndFileSha256(@Param("userId") Long userId, @Param("fileSha256") String fileSha256);
    
    /**
     * 获取用户上传统计信息
     */
    @Query("SELECT " +
           "COUNT(us) as totalSessions, " +
           "SUM(CASE WHEN us.status = 'COMPLETED' THEN 1 ELSE 0 END) as completedSessions, " +
           "SUM(CASE WHEN us.status = 'FAILED' THEN 1 ELSE 0 END) as failedSessions, " +
           "SUM(CASE WHEN us.status = 'UPLOADING' THEN 1 ELSE 0 END) as uploadingSessions " +
           "FROM UploadSession us WHERE us.userId = :userId")
    Object[] getUserUploadStats(@Param("userId") Long userId);
    
    /**
     * 查找需要清理的临时文件会话
     */
    @Query("SELECT us FROM UploadSession us WHERE us.status IN ('FAILED', 'EXPIRED') AND us.createdAt < :before")
    List<UploadSession> findSessionsForCleanup(@Param("before") LocalDateTime before);
}
